﻿//========================================================= 
/**@file screenshot_ocr.h
 * @brief 屏幕截取OCR识别
 * 
 * @date 2018-09-18   14:14:17
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_SCREENSHOT_OCR_H_
#define _LIBZHOUYB_SCREENSHOT_OCR_H_
//--------------------------------------------------------- 
#include "screenshot.h"

#include <tesseract/baseapi.h>
#include <tesseract/renderer.h>

#pragma comment(lib, "tesseract40.lib")
//--------------------------------------------------------- 
namespace zhou_yb {
namespace wrapper {
namespace zabbix_extractor {
//--------------------------------------------------------- 
/**
 * @brief 屏幕截取OCR识别监控项
 * @date 2018-09-18 14:41
 */
class screenshot_ocr_monitor
{
public:
    typedef string value_type;

    static string imageOCR_UTF8(const char* pathJpg, const char* result, 
        const char* lang = "eng", const char* datapath = NULL)
    {
        string file = result;
        {
            tesseract::TessBaseAPI api;
            api.SetOutputName(result);
            if(api.Init(datapath, lang, tesseract::OEM_DEFAULT))
                return "{\"exception\":\"init tessdata failed\"}";
            tesseract::TessTextRenderer renderer(result);
            if(!api.ProcessPages(pathJpg, NULL, 0, &renderer))
                return "{\"exception\":\"ocr process failed\"}";
            file += '.';
            file += renderer.file_extension();
        }
        string text = FileHelper::ReadToEnd(file.c_str());
        FolderHelper::EraseFile(file.c_str());
        ByteBuilder buff;
        const byte EOF_END[] = { 0x0A, 0x0C };
        const size_t EOF_LEN = 2;
        if(StringConvert::EndWith(ByteArray(text.c_str(), text.length()), ByteArray(EOF_END, EOF_LEN)))
        {
            container_helper<string>::pop_back(text, EOF_LEN);
        }
        return text;
    }

    static void parseRect(const string& sJson, ColorRect& rect, double& zoomSize, string& lang, list_t<COLORREF>& rgbList, COLORREF& backgroundRGB)
    {
        StringArguments arg;
        RapidJsonArgParser parser;
        parser.Parse(ByteArray(sJson.c_str(), sJson.length()), arg);

        rect.Left = arg["Left"].To<LONG>(0);
        rect.Top = arg["Top"].To<LONG>(0);
        rect.Width = arg["Width"].To<LONG>(0);
        rect.Height = arg["Height"].To<LONG>(0);
        zoomSize = arg["ZoomSize"].To<double>(0);
        lang = arg["Language"].To<string>("chi_sim");
        
        string sBackground = "";
        if(arg.Get("Background", sBackground))
        {
            backgroundRGB = screenshot_monitor::parseRGB(sBackground);
        }

        list_t<string> rgbs;
        arg.Get("RGB", rgbs);
        list_t<string>::const_iterator itr;
        for(itr = rgbs.begin(); itr != rgbs.end(); ++itr)
        {
            rgbList.push_back();
            rgbList.back() = screenshot_monitor::parseRGB(*itr);
        }
    }

    static void ScreenShotCallback(pointer pArg, HWND hWnd, HDC hDC,
        const RECT& rect, const IStringArguments& customer, string& rlt)
    {
        list_t<string> colors;
        customer.Get("OCR", colors);

        list_t<string>::iterator itr;
        string sRlt = "";
        size_t count = 0;
        string captureDir = customer["CaptureDir"].To<string>(".\\");
        string processName = customer["Process"].To<string>();
        StringHelper::FormatDir(captureDir);
        string ocrName = captureDir;
        ocrName += processName;
        if(processName.length() > 0)
            ocrName += '_';
        ocrName += "ocr_";
        for(itr = colors.begin(); itr != colors.end(); ++itr)
        {
            ColorRect r;
            double zoomSize = 0;
            string lang = "";
            list_t<COLORREF> rgbList;
            COLORREF backgroundRGB = RGB(255, 255, 255);
            if(count > 0)
                sRlt += ",";
            parseRect(*itr, r, zoomSize, lang, rgbList, backgroundRGB);
            ++count;
            // 没有需要计算的点
            if(r.Width < 1 || r.Height < 1)
                continue;
            // 截取图片数据
            string bmpFile = ocrName;
            bmpFile += ArgConvert::ToString(count);
            string result = bmpFile;
            bmpFile += ".bmp";
            // 删除历史文件
            FolderHelper::EraseFile(bmpFile.c_str());

            ByteBuilder bmpBuff;
            BITMAP bmp = { 0 };
            HWndHelper::CaptureBmpToBuffer(hDC, rect.left + r.Left, rect.top + r.Top, r.Width, r.Height, bmpBuff, &bmp, zoomSize);
            // 像素替换
            if(rgbList.size() > 0)
            {
                for(LONG x = 0; x < bmp.bmWidth; ++x)
                {
                    for(LONG y = 0; y < bmp.bmHeight; ++y)
                    {
                        COLORREF c = HWndHelper::GetColor(bmpBuff, x, y, bmp);
                        bool isContains = list_helper<COLORREF>::contains(rgbList, c);
                        // 不是需要保留的颜色
                        if(!isContains)
                        {
                            HWndHelper::SetColor(bmpBuff, x, y, bmp, backgroundRGB);
                        }
                    }
                }
            }
            HWndHelper::SaveToBmp(bmpBuff, bmp, bmpFile.c_str());
            // ocr识别
            sRlt += imageOCR_UTF8(bmpFile.c_str(), result.c_str(), lang.c_str(), ".\\tessdata");
        }
        rlt = sRlt;
    }

    static value_type execute()
    {
        return "";
    }
};
//--------------------------------------------------------- 
} // namespace zabbix_extractor 
} // namespace wrapper
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_SCREENSHOT_OCR_H_
//========================================================= 